<?php
/* *
 * 公共
*/

namespace Common\Model;
use Common\Model\CommonModel;

abstract class DfcommonModel extends CommonModel {
	
 protected $_fieldList = array();
    protected $_pk = 'id';
    /**
     * 返回主键
     * @return string
     */
    public function _getPk() {
    	return $this->_pk;
    }
    /**
     * 获取模型对象的字段描述
     * @return array
     */
    public function _getLang ()
    {
        $langs = array();
        foreach ($this->getFieldList() as $field => $item) {
            $langs[$field] = $item;
	        if(preg_match("#\(.*\)#", $item['lang'], $match)) {
	        	$langs[$field]['show_type'] = 'radio';
	        	$match[0] = trim($match[0], "() ");
	        	$delimiter = " ";
	        	if (strpos($match[0], ",") !== false) {
	        		$delimiter = ",";
	        	}
	        	$optionList = explode($delimiter, $match[0]);
	        	foreach($optionList as $option) {
	        		$langs[$field]['data'][intval($option)] = str_replace(intval($option), '', $option);
	        	}
	        }
	        
        }
        return $langs;
    }

    /**
     * 获取模型配置 字段配置列表
     * @return array
     */
    public function getFieldList()
    {
        if ( !empty($this->_fieldList)) {
            return $this->_fieldList;
        } else {
            $prefix  = self::$confArray[$this->dbType]['db_prefix'];
            $tabName = $this->tabName;
            if (!empty($prefix)) {
                $tabName = $prefix . $this->tabName;
            }
            $sql = "show create table `".$tabName."`";
            $fields = $this->query($sql);
            $data = $this->paramCreateSql($fields[0]["Create Table"]);
            
            foreach ($data['field'] as $field => $item) {
            	$langs[$field] = $item;
            	if(preg_match("#\(.*\)#", $item['lang'], $match)) {
            		$langs[$field]['show_type'] = 'radio';
            		$match[0] = trim($match[0], "() ");
            		$delimiter = " ";
            		if (strpos($match[0], ",") !== false) {
            			$delimiter = ",";
            		}
            		$optionList = explode($delimiter, $match[0]);
            		foreach($optionList as $option) {
            			$langs[$field]['data'][intval($option)] = str_replace(intval($option), '', $option);
            		}
            	}
            }
            
            $data['field'] = $langs;
            
            echo "<hr ><pre>#需要复制到对应的dao文件中\n";
            echo "// 数据表字段说明配置\n";
            echo 'protected $_fieldList =';
            echo var_export($data['field'], true),';';
            echo "</pre><hr >";
        }
        
        
        
        
        
    }
    /**
     * 根据sql语句获取数据表字段
     * @param file_path $sqlFile sql文件路径
     * @return array 分析后的sql字段
     */
    private function paramCreateSql ($createSql)
    {
        echo "<hr ><pre>数据表结构：\n",$createSql,"</pre><hr >";
        $field = array(
            'field' => '`(.*)`',
            'type' => '(\w*)',
            'length' => '\(([^\)]*)\){0,1}',
            'unsigned' => '(unsigned){0,1}',
            'null' => '(NOT NULL|NULL){0,1}',
            'aotu' =>'(AUTO_INCREMENT){0,1}',
            'default' => '(?:DEFAULT \'([^\']*)\'){0,1}',
            'comment' => '(?:COMMENT \'([^\']*)\'){0,1}',
        );
        $fields = implode('\s{0,1}', $field);
        $patternList = array(
            'name' => 'CREATE TABLE `(.*)`',
            'field' => $fields,
            'pkey' => 'PRIMARY KEY \(`(.*)`\)',
            'cname' => 'CHARSET=utf8 COMMENT=\'(.*)\''
        );
    
        $data = array();
        $createSql = explode("\n", $createSql);
        foreach ($createSql as $line) {
            foreach ($patternList as $type => $pattern) {
                if (preg_match(sprintf("#%s#", $pattern), $line, $match)) {
                    if ('field' == $type) {
                        array_shift($match);
                        $pattern = array_combine(array_keys($field), $match);
                        if (!$pattern && $match[1]) {
                        	echo "<font color=red>此处字段没有成功解析，请注意</font>[{$match[0]}]<br> \n";
                        }
                        list ($item['type'], $item['length'], $item['lang']) = array($pattern['type'], $pattern['length'], $pattern['comment']);
                        if (empty($item['lang'])) {
                            $item['lang'] = $pattern['field'];
                        }
                        if (!empty($pattern['field'])) {
                            $data[$type][$pattern['field']] = $item;
                        }
                    } else {
                        $data[$type] = $match[1];
                    }
                }
            }
        }
        return $data;
    }

    // ===================== model公用方法 ==== 开始 ====start=============================
    /**
     * 根据主键ID数组，获取数据列表
     * @param array $ids
     * @return array 数据列表
     */
    public function _getListByIds($ids, $filed='*') {
        $where = sprintf("%s in(%s)", $this->_pk, implode(',', (array)$ids));
        $rs = $this->field($filed)->where($where)->order($this->_pk . ' desc')->select();
        if (is_array($rs)) {
            $data = array();
            foreach($rs as $k => $v) {
                $data[$v[$this->_pk]] = $v;
            }
            return $data;
        }
        return $rs;
    }
    /**
     * 获取数据列表 (前置条件拼装)
     */
    public function _getList_before($where) {
    	$langs = $this->_getLang();
    	$where = array_intersect_key($where, $langs);
    	foreach ($where as $field => &$value) {
    		switch ($langs[$field]["show_type"]) {
    			case 'datetime' : 
    				$value = array_filter($value);
    				if(!empty($value)) {
	    				$value = array_map('strtotime', $value);
	    				$value = '`'.$field.'`' . ' BETWEEN ' . implode(" AND ", $value) ;
    				} else {
    					unset($where[$field]);
    				}
    			break;
    			case 'textedit':
    			case 'text':
    				$value = '`'.$field.'`' . 'like "%' .$value.'%"' ;
    			break;
    			case 'radio':
    			case 'checkbox':
    			default:
    				if (is_array($value)) {
	    				$value = '`'.$field.'`' . ' IN("' .implode('","', $value).'")' ;
    				} else {
	    				$value = '`'.$field.'`' . '="' .$value.'"' ;
    				}
    			break;
    		}
    	}
    	$where = implode(' AND ', $where);
    	return $where;
    }
    /**
     * 获取数据列表 (前置条件拼装) 状态条件
     */
    public function _getList_before_status($sql_where, $where) {
    	$langs = $this->_getLang();
    	if (isset($langs['status'])) {
    		$status = isset($where['status']) ? $where['status'] : 1;
    		if (is_string($sql_where) && strstr($sql_where, 'status') === false) {
    			$sql_where .= ($sql_where ? " AND " : " ") . "status=".$status;
    		} elseif (is_array($sql_where) && isset($sql_where['status']) == false) {
    			$sql_where['status'] = $status;
    		}
    	}
    	return $sql_where;
    }
    /**
     * 获取数据列表
     * @param int $page 当前页面数
     * @param array $where 查询条件
     * @param int $pagesize 分页大小
     * @return array 数据列表
     */
    public function _getList($where, $limit) {
    	$sql_where = $this->_getList_before($where);
    	$sql_where = $this->_getList_before_status($sql_where, $where);
    	
    	$rs = $this->where($sql_where)->order($this->_pk . ' desc')->limit($limit)->select();
    	
    	$langs = $this->_getLang();
    	foreach ($rs as & $item) {
    		foreach ($item as $k => & $v) {
    			if (isset($langs[$k]['show_type'])) {
    				switch ($langs[$k]['show_type']) {
    					case 'radio':
    						$v = $langs[$k]['data'][$v];
    						break;
    	
    					case 'select':
    						$v = isset($langs[$k]['data'][$v]) ? $langs[$k]['data'][$v] : '--无--';
    						break;
    	
    					case 'datetime':
    						$v = date("Y-m-d H:i", $v);
    						break;
    					case 'multiImage':
    						$v = json_decode($v);
    						break;
    				}
    			}
    		}
    		// 修改添加时间显示格式
    		if (isset($item['cdate'])) {
    			if (date("Y", $item['cdate']) < 2017 && date("Y", $item['cdate']) >= 2014) {
    				$item['cdate'] = date("Y-m-d H:i", $item['cdate']);
    			} else {
    				$item['cdate'] = substr($item['cdate'], 0, 4) . "-" . substr($item['cdate'], 4, 2) . "-" . substr($item['cdate'], 6, 2) . " " . substr($item['cdate'], 8, 2) . ":00";
    			}
    		}
    		// 修改添加时间显示格式
    		if (isset($item['udate'])) {
    			if (date("Y", $item['udate']) < 2017 && date("Y", $item['udate']) >= 2014) {
    				$item['udate'] = date("Y-m-d H:i", $item['udate']);
    			} else {
    				$item['udate'] = substr($item['udate'], 0, 4) . "-" . substr($item['udate'], 4, 2) . "-" . substr($item['udate'], 6, 2) . " " . substr($item['udate'], 8, 2) . ":00";
    			}
    		}
    	}
    	
    	
    	return $rs;
    }
    /**
     * 获取数据总数
     * @param array $where 查询条件
     * @return array 数据总数
     */
    public function _count($where='') {
    	$sql_where = $this->_getList_before($where);
    	$sql_where = $this->_getList_before_status($sql_where, $where);
    	$rs = $this->where($sql_where)->count();
    	return $rs;
    }
    /**
     * 获取 详细信息
     * @param int $id 主键ID
     * @return array 详细信息
     */
    public function _getInfo($id) {
        $pk = $this->_getPk();
    	$info = $this->where(array($pk => $id))->find();
    	$langs = $this->_getLang();
    	foreach ($info as $k => & $v) {
    		if (isset($langs[$k]['show_type'])) {
    			switch ($langs[$k]['show_type']) {
    				case 'radio':
    					$v = $langs[$k]['data'][$v];
    					break;
    				case 'select':
    					$v = isset($langs[$k]['data'][$v]) ? $langs[$k]['data'][$v] : '--无--';
    					break;
    				case 'datetime':
    					$v = date("Y-m-d H:i", $v);
    					break;
    				case 'multiFile':
    				case 'multiImage':
    					$v = json_decode($v, true);
    					break;
    			}
    		}
    	}
    	
    	return $info;
    }
    /**
     * 添加数据
     * @param array $data 要添加的数据
     * @return boolean
     */
    public function _add($data) {
    	$langs = $this->_getLang();
    	if (isset($langs['cdate'])) {
    		$data['cdate'] = time();
    	}
    	if (isset($langs['ctime'])) {
    		$data['ctime'] = time();
    	}
    	$rs = $this->add($data);
    	return $rs;
    }
    /**
     * 修改数据
     * @param array $data 要添加的数据
     * @return boolean
     */
    public function _save($data) {
    	$langs = $this->_getLang();
    	foreach ($langs as $field => $conf) {
    		if ($this->_getPk() != $field &&  isset($conf['disadle']) && $conf['disadle']==true) {
    			unset($data[$field]);
    		}
    	}
    	if (isset($langs['udate'])) {
    		$data['udate'] = time();
    	}
    	if (isset($langs['utime'])) {
    		$data['utime'] = time();
    	}
    	$rs = $this->save($data);
    	return $rs;
    }
    /**
     * 删除一条数据
     * @param int $id 主键ID
     */
    public function _del($id) {
    	return $rs = $this->where(array('id' => $id))->delete();
    }
    
    /**
     * 支持一次插入多句记录
     * @datas array    //数据记录
     * @table string   //表名
     */
    function batchInsert($datas, $options, $need_update = false){
    	 
    	$tablename = $this->getTableName ();
    	if (! is_array ( $datas ) || count ( $datas ) < 1) {
    		$this->error = "方法 batchInsert() 第1个参数不是数组错误， 表名为 {$tablename} ";
    		return false;
    	}
    
    	$cols = array_keys ( current ( $datas ) );
    	$values = array ();
    	foreach ( $datas as $row ) {
    		if (! is_array ( $row ) || count ( $row ) < 1) {
    			$this->error = "方法 insert() 参数错误， 表名为 {$tablename} ";
    			return false;
    		}
    		$single = array ();
    		foreach ( $row as $field => $value ) {
    			if (! isset ( $value )) {
    				$single [] = '';
    			} else {
    				$single [] = addslashes ( $value );
    			}
    		}
    		$values [] = "('" . implode ( '\',\'', $single ) . "')";
    	}
    
    	$scols = implode ( "`,`", $cols );
    	$values = implode ( ",", $values );
    	$sql = "INSERT INTO  `{$tablename}` (`{$scols}`) VALUES {$values}";
    	if ($need_update == true) {
    		$update_str = $this->duplicateUpdate ( $cols );
    		$sql .= $update_str;
    	}
    	$result = $this->execute($sql);
    	return $result;
    }
    /**
     *  获取DUPLICATE KEY UPDATE的sql语句
     */
    private function duplicateUpdate($fields){
    	//增加update
    	$sql = " ON DUPLICATE KEY UPDATE ";
    	$update_str = '';
    	foreach($fields as $field)
    	{
    		if ('cdate' != $field) {
    			$update_str .= "`" . $field . "` = VALUES(`" . $field . "`),";
    		}
    	}
    	$update_str = substr($update_str, 0 , -1);
    	$sql .= $update_str;
    	return $sql;
    }
    // ===================== model公用方法 ==== 结束 ====end=============================
}